package com.thanos.api.storage;

import com.thanos.api.storage.contract.SimpleStorage;
import com.thanos.common.crypto.key.asymmetric.SecureKey;
import com.thanos.web3j.config.SystemConfig;
import com.thanos.web3j.crypto.Credentials;
import com.thanos.web3j.protocol.Web3j;
import com.thanos.web3j.model.ThanosTransactionReceipt;
import com.thanos.web3j.protocol.manage.Web3Manager;
import com.thanos.web3j.utils.ConfigResourceUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.spongycastle.util.encoders.Hex;

import javax.annotation.PostConstruct;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * StorageService.java description：Thanos链存储服务类
 *
 * @Author create on 2024-12-19
 */
@Service
public class StorageService {
    
    private static final Logger logger = LoggerFactory.getLogger(StorageService.class);
    
    @Value("${contract.storage.address:}")
    private String configuredContractAddress;
    
    private SystemConfig systemConfig;
    private Web3Manager web3Manager;
    private Credentials contractOwnerCredentials;
    private String contractAddress;
    
    @PostConstruct
    public void init() {
        try {
            // 初始化系统配置
            systemConfig = ConfigResourceUtil.loadSystemConfig();
            ConfigResourceUtil.loadLogConfig(systemConfig.logConfigPath());
            
            // 创建合约所有者凭证
            SecureKey secureKey = SecureKey.fromPrivate(Hex.decode("010001308f761b30da0baa33457550420bb8938d040a0c6f0582d9351fd5cead86ff11"));
            contractOwnerCredentials = Credentials.create(secureKey);
            
            // 创建Web3Manager
            web3Manager = new Web3Manager(systemConfig);
            
            // 检查是否已有合约地址配置，如果没有则部署新合约
            logger.info("Configured contract address from application.yml: '{}'", configuredContractAddress);
            if (configuredContractAddress != null && !configuredContractAddress.trim().isEmpty()) {
                contractAddress = configuredContractAddress.trim();
                logger.info("Using configured storage contract at address: {}", contractAddress);
            } else {
                logger.info("No contract address configured, deploying new contract...");
                Web3j web3j = web3Manager.getHttpWeb3jRandomly();
                contractAddress = StorageContractHelper.deploy(web3j, contractOwnerCredentials);
                logger.info("New storage contract deployed at address: {}", contractAddress);
                logger.info("Please add 'contract.storage.address: {}' to application.yml to reuse this contract", contractAddress);
            }
            
        } catch (Exception e) {
            logger.error("Failed to initialize StorageService: {}", e.getMessage(), e);
            throw new RuntimeException("Service initialization failed", e);
        }
    }
    
    /**
     * 部署新合约
     */
    public Map<String, Object> deployContract() {
        Map<String, Object> result = new HashMap<>();
        try {
            Web3j web3j = web3Manager.getHttpWeb3jRandomly();
            String newContractAddress = StorageContractHelper.deploy(web3j, contractOwnerCredentials);
            
            result.put("success", true);
            result.put("contractAddress", newContractAddress);
            result.put("message", "Contract deployed successfully");
            
            logger.info("New storage contract deployed at address: {}", newContractAddress);
            
        } catch (Exception e) {
            logger.error("Failed to deploy contract: {}", e.getMessage(), e);
            result.put("success", false);
            result.put("error", e.getMessage());
        }
        return result;
    }
    
    /**
     * 设置键值对
     */
    public Map<String, Object> setKeyValue(String key, String value) {
        Map<String, Object> result = new HashMap<>();
        try {
            Web3j web3j = web3Manager.getHttpWeb3jRandomly();
            ThanosTransactionReceipt receipt = StorageContractHelper.setKeyValue(web3j, contractAddress, contractOwnerCredentials, key, value);
            
            result.put("success", true);
            result.put("message", String.format("Successfully set key '%s' to value '%s'", key, value));
            result.put("receipt", receipt);
            
            logger.info("Set key: {}, value: {}", key, value);
            
        } catch (Exception e) {
            logger.error("Failed to set key-value pair: {}", e.getMessage(), e);
            result.put("success", false);
            result.put("error", e.getMessage());
        }
        return result;
    }
    
    /**
     * 获取键对应的值
     */
    public Map<String, Object> getKeyValue(String key) {
        Map<String, Object> result = new HashMap<>();
        try {
            Web3j web3j = web3Manager.getHttpWeb3jRandomly();
            String value = StorageContractHelper.getKeyValue(web3j, contractAddress, contractOwnerCredentials, key);
            
            result.put("success", true);
            result.put("key", key);
            result.put("value", value);
            
            logger.info("Retrieved key: {}, value: {}", key, value);
            
        } catch (Exception e) {
            logger.error("Failed to get value for key '{}': {}", key, e.getMessage(), e);
            result.put("success", false);
            result.put("error", e.getMessage());
        }
        return result;
    }
    
    /**
     * 执行基础存储测试
     */
    public Map<String, Object> runBasicStorageTest() {
        Map<String, Object> result = new HashMap<>();
        try {
            logger.info("=== Running Basic Storage Test ===");
            
            // 测试用例1: 设置和获取基本键值对
            Web3j web3j = web3Manager.getHttpWeb3jRandomly();
            StorageContractHelper.setKeyValue(web3j, contractAddress, contractOwnerCredentials, "name", "Alice");
            
            web3j = web3Manager.getHttpWeb3jRandomly();
            String value = StorageContractHelper.getKeyValue(web3j, contractAddress, contractOwnerCredentials, "name");
            logger.info("Retrieved value for 'name': {}", value);
            
            // 测试用例2: 设置和获取数字
            web3j = web3Manager.getHttpWeb3jRandomly();
            StorageContractHelper.setKeyValue(web3j, contractAddress, contractOwnerCredentials, "age", "25");
            
            web3j = web3Manager.getHttpWeb3jRandomly();
            String ageValue = StorageContractHelper.getKeyValue(web3j, contractAddress, contractOwnerCredentials, "age");
            logger.info("Retrieved value for 'age': {}", ageValue);
            
            // 测试用例3: 更新已存在的键
            web3j = web3Manager.getHttpWeb3jRandomly();
            StorageContractHelper.setKeyValue(web3j, contractAddress, contractOwnerCredentials, "name", "Bob");
            
            web3j = web3Manager.getHttpWeb3jRandomly();
            String updatedValue = StorageContractHelper.getKeyValue(web3j, contractAddress, contractOwnerCredentials, "name");
            logger.info("Updated value for 'name': {}", updatedValue);
            
            // 测试用例4: 获取不存在的键
            web3j = web3Manager.getHttpWeb3jRandomly();
            String nonexistentValue = StorageContractHelper.getKeyValue(web3j, contractAddress, contractOwnerCredentials, "nonexistent");
            logger.info("Value for nonexistent key: '{}'", nonexistentValue);
            
            result.put("success", true);
            result.put("message", "Basic storage test completed successfully");
            Map<String, String> testResults = new HashMap<>();
            testResults.put("name", updatedValue);
            testResults.put("age", ageValue);
            testResults.put("nonexistent", nonexistentValue);
            result.put("testResults", testResults);
            
        } catch (Exception e) {
            logger.error("Error in runBasicStorageTest: {}", e.getMessage(), e);
            result.put("success", false);
            result.put("error", e.getMessage());
        }
        return result;
    }
    
    /**
     * 执行多用户存储测试
     */
    public Map<String, Object> runMultiUserStorageTest() {
        Map<String, Object> result = new HashMap<>();
        try {
            logger.info("=== Running Multi-User Storage Test ===");
            
            // 创建多个用户
            List<Credentials> users = StorageContractHelper.createUsers(3);
            
            // 每个用户设置不同的键值对
            for (int i = 0; i < users.size(); i++) {
                Web3j web3j = web3Manager.getHttpWeb3jRandomly();
                String key = "user" + i + "_data";
                String value = "User " + i + " information";
                StorageContractHelper.setKeyValue(web3j, contractAddress, users.get(i), key, value);
                logger.info("User {} set key: {}, value: {}", i, key, value);
            }
            
            // 验证每个用户设置的数据
            Map<String, String> userResults = new HashMap<>();
            for (int i = 0; i < users.size(); i++) {
                Web3j web3j = web3Manager.getHttpWeb3jRandomly();
                String key = "user" + i + "_data";
                String retrievedValue = StorageContractHelper.getKeyValue(web3j, contractAddress, users.get(i), key);
                logger.info("User {} retrieved key: {}, value: {}", i, key, retrievedValue);
                userResults.put(key, retrievedValue);
            }
            
            // 测试用户间数据共享（所有用户都能访问相同的存储）
            Web3j web3j = web3Manager.getHttpWeb3jRandomly();
            String sharedValue = StorageContractHelper.getKeyValue(web3j, contractAddress, users.get(0), "user1_data");
            logger.info("User 0 accessing User 1's data: {}", sharedValue);
            
            result.put("success", true);
            result.put("message", "Multi-user storage test completed successfully");
            result.put("userResults", userResults);
            result.put("sharedAccess", sharedValue);
            
        } catch (Exception e) {
            logger.error("Error in runMultiUserStorageTest: {}", e.getMessage(), e);
            result.put("success", false);
            result.put("error", e.getMessage());
        }
        return result;
    }
    
    /**
     * 获取当前合约地址
     */
    public String getContractAddress() {
        return contractAddress;
    }
    

}